package com.atguigu.java;

import org.junit.Test;

import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

/**
 *      一、流的分类：
 *          1.操作数据单位：字节流、字符流
 *          2.数据的流向：输入流、输出流
 *          3.流的角色：节点流、处理流
 *
 *      二、流的体系结构
 *
 *          抽象基类                        节点流(或文件流)                                       缓冲流(处理流的一种)
 *          InputStream                     FileInputStream (read(byte[] arr)                     BufferedInputStream (read(byte[] arr)
 *          OutPutStream                    FileOutputStream (write(byte[] arr,0,len)             BufferedOutputStream (write(byte[] arr,0,len) / flush()
 *          Reader                          FileReader (read(char[] arr)                          BufferedReader (read(char[] arr / readLine())
 *          Writer                          FileWriter (write(char[] arr,0,len)                   BufferedWriter (write(char[] arr,0,len) / flush()
 *
 *
 *     对其他物理连接，比如数据库连接、输入流输出流、Socket连接，JVM无能为力,必须手动关闭这些资源
 *
 *
 * @author : leimingchao
 * @date Date : 2021年10月09日 21:46
 */
public class FileReaderWriterTest {

    public static void main(String[] args) {
        //相较于当前工程
        File file = new File("hello.txt");
        System.out.println(file.getAbsolutePath());

        File file1 = new File("day09\\hello.txt");
        System.out.println(file1.getAbsolutePath());
    }

    /**
     * 将day09下的hello.txt文件内容读入程序中，并输出到控制台
     *
     * 说明点：
     *      1.read()的理解：返回读入的一个字符，如果达到文件末尾，返回-1.
     *      2.异常的处理：为了保证流资源一定可以执行关闭操作。需要使用try-catch-finally处理
     *      3.读入的文件一定要存在，否则就会报FileNotFoundException
     */
    @Test
    public void testFileReader() {
        FileReader fileReader = null;
        try {
            //相较于当前Module下
            //1.实例化File类对象，指明要操作的文件
            File file = new File("hello.txt");
            //2.提供具体的流
            fileReader = new FileReader(file);
            //3.数据的读入过程
            //read():返回读入的一个字符。如果达到文件末尾，返回-1。
            //方式一：
            // int read = fileReader.read();
            // while (read != -1) {
            //     System.out.print((char) read);
            //     read = fileReader.read();
            // }
            //方式二：语法上针对于方式一的修改
            int read;
            while ((read = fileReader.read()) != -1) {
                System.out.print((char) read);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4.流的关闭操作
            // try {
            //     if (fileReader != null) {
            //         fileReader.close();
            //     }
            // } catch (IOException e) {
            //     e.printStackTrace();
            // }
            //或
            if (fileReader != null) {
                try {
                    fileReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 对read()操作升级：使用read的重载方法
     */
    @Test
    public void testFileReader1() {
        //1.File类的一个实例化
        FileReader fileReader = null;
        try {
            File file = new File("hello.txt");
            //2.FileReader流的实例化
            fileReader = new FileReader(file);
            //3.读入的操作细节
            //read(char[] arr):返回每次读入arr数组中的字符个数。如果达到文件末尾，返回-1.
            char[] arr = new char[5];
            int len;
            while ((len = fileReader.read(arr)) != -1) {
                //方式一：
                //错误的写法：
                // for (int i = 0; i < arr.length; i++) {
                //     System.out.print(arr[i]);
                // }
                //正确的写法:
                // for (int i = 0; i < len; i++) {
                //     System.out.print(arr[i]);
                // }
                //方式二：
                //错误写法：对应方式一的错误的写法
                // String str = new String(arr);
                // System.out.print(str);
                //正确的写法：
                String str = new String(arr,0,len);
                System.out.print(str);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4.资源的关闭
            if (fileReader != null) {
                try {
                    fileReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 从内存中写出数据到硬盘的文件里
     * 说明：
     *      1.输出操作，对应的File可以不存在的。并不会报异常
     *      2.  File对应的硬盘中的文件如果不存在，在输出的过程中，会自动创建此文件。
     *          File对应的硬盘中的文件如果存在：
     *              如果流使用的构造器是：FileWriter(file,false) / FileWriter(file)：对原有文件的覆盖
     *              如果流使用的构造器是：FileWriter(file,true)：不会对原有文件覆盖，而是在原有文件基础上追加内容
     */
    @Test
    public void testFileWriter() {
        FileWriter fileWriter = null;
        try {
            //1.提供File类的对象，指明写出到的文件
            File file = new File("hello1.txt");
            //2.提供FileWriter的对象，用于数据的写出
            fileWriter = new FileWriter(file);
            //3.写出的操作
            fileWriter.write("I have a dream!\n");
            fileWriter.write("you need to have a dream!");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fileWriter != null) {
                //4.流资源的关闭
                try {
                    fileWriter.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }

    @Test
    public void testFileReaderFileWriter() {
        FileReader fileReader = null;
        FileWriter fileWriter = null;
        try {
            //1.创建File类的对象，指明读入和写出的文件
            File srcFile = new File("hello.txt");
            File destFile = new File("hello2.txt");

            //错误的，不能使用字符流来处理图片等字节数据
            // File srcFile = new File("爱情与友情.jpg");
            // File destFile = new File("爱情与友情1.jpg");
            //2.创建输入流和输出流的对象
            fileReader = new FileReader(srcFile);
            fileWriter = new FileWriter(destFile);
            //3.数据的读入和写出操作
            char[] arr = new char[5];
            //记录每次读入到arr数组中的字符的个数
            int len;
            while ((len = fileReader.read(arr)) != -1) {
                //每次写出len个字符
                fileWriter.write(arr,0,len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4.关闭流资源
            //方式一：
            // try {
            //     if (fileWriter != null) {
            //         fileWriter.close();
            //     }
            // } catch (IOException e) {
            //     e.printStackTrace();
            // } finally {
            //
            //     try {
            //         if (fileReader != null) {
            //             fileReader.close();
            //         }
            //     } catch (IOException e) {
            //         e.printStackTrace();
            //     }
            // }
            //方式二：
            try {
                if (fileWriter != null) {
                    fileWriter.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

            try {
                if (fileReader != null) {
                    fileReader.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
}
